//== SAGITTARIUS ============================================================================

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGITTARIUS__SAGITTARIUS_LOG__H_
#define __SAGITTARIUS__SAGITTARIUS_LOG__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCommon.h"
#include "sagittarius/core/SagittariusException.hpp"
#include "sagittarius/core/SagittariusConfigure.h"

#include "sagittarius/patterns/SagittariusSingleton.hpp"
#include "sagittarius/threading/SagittariusThreading.hpp"

#include <iostream>
#include <fstream>

namespace Sagittarius
{
    
    class __SagittariusLog
    {
        public:
            
            ~__SagittariusLog()
            {
                close();
            }
            
            void open(const String& filepath)
            {
                RecursiveLock l(_mut);
                //SAGITTARIUS_ASSERT(false);
                _file.open(filepath.c_str(), std::fstream::out);
                if(_file.fail())
                    SAGITTARIUS_THROW(FileWriteFailureException, "Failed to open logfile " + filepath, "__SagittariusLog::open");
                _is_open = true;
                _use_file = true;
            }
            
            void close()
            {
                RecursiveLock l(_mut);
                _file.close();
            }
            
            void suppress()
            {
                RecursiveLock l(_mut);
                _suppressed = true;
            }
            
            void unsuppress()
            {
                RecursiveLock l(_mut);
                _suppressed = false;
            }
            
            /*template<class T>
            __SagittariusLog& operator<< (const T& data)
            {
                SAGITTARIUS_ASSERT( _is_open );
                _file << data;
                return *this;
            }*/
            
        private:
            __SagittariusLog()
                : _is_open(false), _use_file(false), _suppressed(false)
            {
            }
            
            __SagittariusLog(const __SagittariusLog& other) {}
            const __SagittariusLog& operator=(const __SagittariusLog& other) {}
            const __SagittariusLog* operator&() {}
            
            friend class SagittariusSingleton<__SagittariusLog>;
            template <class T>
            friend std::ostream& operator<< (__SagittariusLog& log, const T& data);
            
            //variables:
            std::fstream _file;
            bool _is_open;
            bool _use_file;
            bool _suppressed;
            
            //mutex
            mutable RecursiveMutex _mut;
            
    };
    
    template <class T>
    std::ostream& operator<< (__SagittariusLog& log, const T& data)
    {
        RecursiveLock l(log._mut);
        if(log._suppressed)
        {
            return log._file;
        }
        if( log._use_file )
        {
            SAGITTARIUS_ASSERT( log._is_open );
            log._file << data;
            return log._file;
        }
        else
        {
            std::cout << data;
            return std::cout;
        }
    }
    
} //namespace Sagittarius

#endif
